package com.umessage.hotel.rest;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import org.apache.shiro.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.riversoft.weixin.pay.util.SignatureUtil;
import com.umessage.common.service.RedisService;
import com.umessage.common.shiro.JwtFilter;
import com.umessage.common.shiro.JwtMemberToken;
import com.umessage.common.util.Atools;
import com.umessage.common.util.HttpUtils;
import com.umessage.common.util.JsonWebTokenUtil;
import com.umessage.hotel.domain.DepositOrder;
import com.umessage.hotel.domain.HotelInfo;
import com.umessage.hotel.domain.MemberAccountLog;
import com.umessage.hotel.domain.MemberInfo;
import com.umessage.hotel.domain.WXUser;
import com.umessage.hotel.domain.WXUserMember;
import com.umessage.hotel.domain.WxCfg;
import com.umessage.hotel.model.MemberModel;
import com.umessage.hotel.model.PayResult;
import com.umessage.hotel.model.PaySignModel;
import com.umessage.hotel.model.SessionModel;
import com.umessage.hotel.model.WXUserModel;
import com.umessage.hotel.service.CouponService;
import com.umessage.hotel.service.DepositOrderService;
import com.umessage.hotel.service.HotelInfoService;
import com.umessage.hotel.service.MemberBaseService;
import com.umessage.hotel.service.MemberInfoService;
import com.umessage.hotel.service.OrderInfoService;
import com.umessage.hotel.service.WXUserMemberService;
import com.umessage.hotel.service.WXUserService;
import com.umessage.hotel.service.WxCfgService;
import com.umessage.hotel.util.AesCbcUtil;
import com.umessage.hotel.util.HotelConstant;
import com.umessage.hotel.util.RestResult;
import com.umessage.hotel.util.RestResultGenerator;
import com.umessage.hotel.util.XmlTool;

import io.jsonwebtoken.SignatureAlgorithm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api("会员管理")
@RestController
@EnableAutoConfiguration
@RequestMapping("/rest/members")
public class MemberResource {

	private final long refreshPeriodTime = 36000L;
	private final long period = 36000L * 24 * 7;// 秒
	@Autowired
	private WXUserService wxUserService;
	@Autowired
	private WXUserMemberService wxUserMemberService;
	@Autowired
	private MemberInfoService memberInfoService;
	@Autowired
	private MemberBaseService memberBaseService;
	@Autowired
	private DepositOrderService depositOrderService;
	@Autowired
	private WxCfgService wxCfgService;
	@Autowired
	private HotelInfoService hotelService;
	@Autowired
	private RedisService redisService;
	@Autowired
	private CouponService couponService;
	@Autowired
	private OrderInfoService orderService;
	@Value("${umessage.miniprogramServerUrl}")
	private String miniprogramServerUrl;

	private DateFormat df = new SimpleDateFormat("YYYY-MM-DD hh:mm:ss");

	/**
	 * 用户登录
	 * 
	 * @param mobile
	 * @param vercode
	 * @return
	 */
	@ApiOperation(value = "会员登录", notes = "会员登录")
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public RestResult<SessionModel> login(String hotelId, String code) {
		// TODO:根据获取到的openid查询数据库，如果存在直接登录；如果该openid不存在，则在新建一个会员信息。
		// 实现用户在服务器
		Subject user = SecurityUtils.getSubject();
		// 验证openid是否合法
		JwtMemberToken jwtToken = new JwtMemberToken(hotelId, code);
		user.login(jwtToken);
		if (user.isAuthenticated()) {
			String openid = (String) user.getPrincipal();
			if(StringUtils.isNotBlank(openid)) {
				WXUser wxUser = wxUserService.findUserByOpenid(openid);
				// 如果用户不存在
				if (wxUser == null) {
					wxUser = new WXUser();
					wxUser.setWxuserId(UUID.randomUUID().toString());
					wxUser.setOpenid(openid);
					wxUser.setRegTime(new Date());
					this.wxUserService.save(wxUser);
					//用户信息绑定会员id(memberId)
					/*MemberInfo memberInfo = new MemberInfo();
				memberInfo.setMemberId(UUID.randomUUID().toString());
				memberInfo.setHotelId(hotelId);
				memberInfo.setMobile("");
				memberInfo.setRealMoney(BigDecimal.ZERO);
				memberInfo.setVirtMoney(BigDecimal.ZERO);
				memberInfo.setLastLoginTime(new Date());
				memberInfo.setGrade(HotelConstant.USER_GRADE_NEW);
				memberInfo.setAddTime(new Date());
				this.memberInfoService.saveMemberNew(memberInfo);*/
					
					WXUserMember wxUserMember = new WXUserMember();
					wxUserMember.setHotelId(hotelId);
					//wxUserMember.setMemberId(memberInfo.getMemberId());
					wxUserMember.setWxuserId(wxUser.getWxuserId());
					this.wxUserMemberService.save(wxUserMember);
					// 获取用户信息
				}
				String jwt = JsonWebTokenUtil.issueJWT(openid, wxUser.getWxuserId(), hotelId, JwtFilter.CLIENT_MINI_PROGRAM,
						period, "user", null, HotelConstant.LOGIN_TYPE_WX, SignatureAlgorithm.HS512);
				
				return RestResultGenerator.genSuccessResult(new SessionModel(jwt, HotelConstant.LOGIN_TYPE_WX));
			}else {
				return RestResultGenerator.genErrorResult("login方法中openid is null"+"酒店id======"+hotelId);
			}
		}
		return RestResultGenerator.genErrorResult("server error");
	}

	private MemberModel wrapMemberModel(MemberInfo memberInfo) {
		MemberModel userinfo = new MemberModel();
		userinfo.setMemberId(memberInfo.getMemberId());
		userinfo.setHotelId(memberInfo.getHotelId());
		userinfo.setRealMoney(memberInfo.getRealMoney());
		userinfo.setVirtMoney(memberInfo.getVirtMoney());
		userinfo.setGrade(memberInfo.getGrade());
		userinfo.setNotifiable(memberInfo.getNotifiable());
		userinfo.setLastLoginTime(df.format(memberInfo.getLastLoginTime()));
		return userinfo;
	}

	@ApiOperation(value = "微信登录", notes = "当前微信登录")
	@RequestMapping(value="/loginagain",method = RequestMethod.GET)
	public RestResult<SessionModel> loginagain(@RequestParam(required = true) String hotelId,@RequestParam(required = true) String encryptionCode,
			@RequestParam(required = true) String iv,@RequestParam(required = true) String code, ServletRequest request) {
		try {
			String type = "1";
			WxCfg wxCfg = wxCfgService.queryWxCfg(hotelId, "1");
			String appId  = wxCfg.getAppId();
			String secret=wxCfg.getSecretKey();
			
			//获取sesiionkey
			String url = "https://api.weixin.qq.com/sns/jscode2session";
			String param="appid="+appId+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code";
			String sendGet = HttpUtils.sendGet(url, param);
			String sessionKey = null;
			if(sendGet !=null){
				JSONObject parseObject = JSONObject.parseObject(sendGet);
				sessionKey = (String) parseObject.get("session_key");
			}
			// 进行解密
			String phoneNumber= null;
			
			String result = AesCbcUtil.decrypt(encryptionCode, sessionKey, iv, "UTF-8");
			if (null != result && result.length() > 0) {
				JSONObject userInfoJSON = JSONObject.parseObject(result);
				phoneNumber = (String) userInfoJSON.get("phoneNumber");
			}

			String openId = (String) request.getAttribute("openid");
			hotelId = (String) request.getAttribute("issuer");
			String subject = (String) request.getAttribute("subject");
			type = (String) request.getAttribute("type");
			String wxUserId = null;
			String memberId = null;
			// 微信登录，未手机登录
			if (HotelConstant.LOGIN_TYPE_WX.equals(type)) {
				wxUserId = subject;
			} else if (HotelConstant.LOGIN_TYPE_MOBILE_ClIENT.equals(type)) {
				memberId = subject;
			} else {
				return RestResultGenerator.genResult(false, null, "invalid data");
			}

			MemberInfo memberInfo = null;
			if (memberId != null) {
				memberInfo = memberInfoService.selectByKey(memberId);
			} else {
				memberInfo = memberInfoService.findMemberByMobile(hotelId, phoneNumber);
			}
			if (memberInfo == null) {
				memberInfo = new MemberInfo();
				memberInfo.setMemberId(Atools.getOneStr());
				memberInfo.setHotelId(hotelId);
				memberInfo.setMobile(phoneNumber);
				memberInfo.setRealMoney(BigDecimal.ZERO);
				memberInfo.setVirtMoney(BigDecimal.ZERO);
				memberInfo.setLastLoginTime(new Date());
				memberInfo.setGrade(HotelConstant.USER_GRADE_MEMBER);
				memberInfo.setAddTime(new Date());
				this.memberInfoService.saveMember(memberInfo);
				//根据wxuserid和hotelid查询酒店 用户关联信息
				WXUserMember wxUserMember=this.wxUserMemberService.findByhotelIdAndWxUserId(hotelId,wxUserId);
				//WXUserMember wxUserMember = new WXUserMember();
				wxUserMember.setHotelId(hotelId);
				wxUserMember.setMemberId(memberInfo.getMemberId());
				wxUserMember.setWxuserId(wxUserId);
				wxUserMember.setBindDate(new Date());
				wxUserMember.setBindStatus("1");
				//this.wxUserMemberService.save(wxUserMember);
				//增加变成修改会员id
				this.wxUserMemberService.updateNotNull(wxUserMember);
			} else {

				WXUserMember wxUserMember = null;
				List<WXUserMember> list = wxUserMemberService.findByMemberId(memberInfo.getMemberId());

				// 遍历绑定关系
				if (list != null && list.size() > 0) {
					for (WXUserMember wm : list) {
						WXUser wu = wxUserService.selectByKey(wm.getWxuserId());
						if (null != wu && openId.equals(wu.getOpenid())) {// 更新绑定时间
							wxUserMember = wm;
							wxUserMember.setBindStatus("1");
							wxUserMember.setBindDate(new Date());
							wxUserMemberService.updateNotNull(wxUserMember);
						} else {
							// 解除其他绑定关系
							wm.setBindStatus("0");
							wm.setUnbindDate(new Date());
							wxUserMemberService.updateAll(wm);
						}
					}
				}

				// 出现没有绑定的情况为：用户领礼金券，后绑定
				if (wxUserMember == null) {
					//根据wxuserid和hotelid查询酒店 用户关联信息
					wxUserMember=this.wxUserMemberService.findByhotelIdAndWxUserId(hotelId,wxUserId);
					if(wxUserMember==null) {
						wxUserMember = new WXUserMember();
						wxUserMember.setHotelId(hotelId);
						wxUserMember.setMemberId(memberInfo.getMemberId());
						wxUserMember.setWxuserId(wxUserId);
						wxUserMember.setBindDate(new Date());
						wxUserMember.setBindStatus("1");
						this.wxUserMemberService.save(wxUserMember);
					}else{
						memberInfo.setGrade(HotelConstant.USER_GRADE_MEMBER);
						this.memberInfoService.updateNotNull(memberInfo);
						wxUserMember.setHotelId(hotelId);
						wxUserMember.setMemberId(memberInfo.getMemberId());
						wxUserMember.setWxuserId(wxUserId);
						wxUserMember.setBindDate(new Date());
						wxUserMember.setBindStatus("1");
						wxUserMemberService.updateNotNull(wxUserMember);
					}
				}
			}

			// 获取用户信息
			String jwt = JsonWebTokenUtil.issueJWT(openId, memberInfo.getMemberId(), hotelId,
					JwtFilter.CLIENT_MINI_PROGRAM, period, "user", null, HotelConstant.LOGIN_TYPE_MOBILE_ClIENT,
					SignatureAlgorithm.HS512);
			return RestResultGenerator.genSuccessResult(new SessionModel(jwt, HotelConstant.LOGIN_TYPE_MOBILE_ClIENT));
		} catch (Exception e) {
			e.printStackTrace();
			return RestResultGenerator.genErrorResult("invalid session id");
		}
	}

	/**
	 * 手机号绑定
	 * 
	 * @param mobile
	 * @param vercode
	 * @return
	 */
	@ApiOperation(value = "绑定手机号", notes = "绑定手机号")
	@RequestMapping(value = "/bindmobile", method = RequestMethod.GET)
	public RestResult<SessionModel> bindmobile(@RequestParam(required = true) String mobile,
			@RequestParam(required = true) String vercode, ServletRequest request) {

		try {
			// "wxxq"为测试验证码
			if (!"wxxq".equals(vercode)) {
				// 验证vercode是否正确,如果正确返回sessionid，如果不正确返回验证失败信息。
				String key = HotelConstant.VERCODE_PREFIX + "_" + HotelConstant.VERCODE_TYPE_CLIENT + "_" + mobile;
				String vc = (String) redisService.get(key);

				if (vc == null) {
					return RestResultGenerator.genErrorResult("unexist vercode");
				}

				if (!vc.equals(vercode)) {
					return RestResultGenerator.genErrorResult("invalid vercode");
				}
			}

			String openId = (String) request.getAttribute("openid");
			String hotelId = (String) request.getAttribute("issuer");
			String subject = (String) request.getAttribute("subject");
			String type = (String) request.getAttribute("type");
			String wxUserId = null;
			String memberId = null;
			// 微信登录，未手机登录
			if (HotelConstant.LOGIN_TYPE_WX.equals(type)) {
				wxUserId = subject;
			} else if (HotelConstant.LOGIN_TYPE_MOBILE_ClIENT.equals(type)) {
				memberId = subject;
			} else {
				return RestResultGenerator.genResult(false, null, "invalid data");
			}

			MemberInfo memberInfo = null;
			if (memberId != null) {
				memberInfo = memberInfoService.selectByKey(memberId);
			} else {
				memberInfo = memberInfoService.findMemberByMobile(hotelId, mobile);
			}
			if (memberInfo == null) {
				memberInfo = new MemberInfo();
				memberInfo.setMemberId(Atools.getOneStr());
				memberInfo.setHotelId(hotelId);
				memberInfo.setMobile(mobile);
				memberInfo.setRealMoney(BigDecimal.ZERO);
				memberInfo.setVirtMoney(BigDecimal.ZERO);
				memberInfo.setLastLoginTime(new Date());
				memberInfo.setMemberNo("");
				memberInfo.setGrade(HotelConstant.USER_GRADE_MEMBER);
				memberInfo.setAddTime(new Date());
				this.memberInfoService.saveMemberNew(memberInfo);

				//根据wxuserid和hotelid查询酒店 用户关联信息
				WXUserMember wxUserMember=this.wxUserMemberService.findByhotelIdAndWxUserId(hotelId,wxUserId);
				//WXUserMember wxUserMember = new WXUserMember();
				wxUserMember.setHotelId(hotelId);
				wxUserMember.setMemberId(memberInfo.getMemberId());
				wxUserMember.setWxuserId(wxUserId);
				wxUserMember.setBindDate(new Date());
				wxUserMember.setBindStatus("1");
				//增加变成修改会员id
				//this.wxUserMemberService.save(wxUserMember);
				this.wxUserMemberService.updateNotNull(wxUserMember);
			} else {

				WXUserMember wxUserMember = null;
				List<WXUserMember> list = wxUserMemberService.findByMemberId(memberInfo.getMemberId());

				// 遍历绑定关系
				if (list != null && list.size() > 0) {
					for (WXUserMember wm : list) {
						WXUser wu = wxUserService.selectByKey(wm.getWxuserId());
						if (null != wu && openId.equals(wu.getOpenid())) {// 更新绑定时间
							wxUserMember = wm;
							wxUserMember.setBindStatus("1");
							wxUserMember.setBindDate(new Date());
							wxUserMemberService.updateNotNull(wxUserMember);
						} else {
							// 解除其他绑定关系
							wm.setBindStatus("0");
							wm.setUnbindDate(new Date());
							wxUserMemberService.updateAll(wm);
							memberInfo.setGrade(HotelConstant.USER_GRADE_MEMBER);
							this.memberInfoService.updateNotNull(memberInfo);
						}
					}
				}

				// 出现没有绑定的情况为：用户领礼金券，后绑定
				if (wxUserMember == null) {
					//根据wxuserid和hotelid查询酒店 用户关联信息
					wxUserMember=this.wxUserMemberService.findByhotelIdAndWxUserId(hotelId,wxUserId);
					if(wxUserMember==null) {
						wxUserMember = new WXUserMember();
						wxUserMember.setHotelId(hotelId);
						wxUserMember.setMemberId(memberInfo.getMemberId());
						wxUserMember.setWxuserId(wxUserId);
						wxUserMember.setBindDate(new Date());
						wxUserMember.setBindStatus("1");
						this.wxUserMemberService.save(wxUserMember);
					}else {
						wxUserMember.setHotelId(hotelId);
						wxUserMember.setMemberId(memberInfo.getMemberId());
						wxUserMember.setWxuserId(wxUserId);
						wxUserMember.setBindDate(new Date());
						wxUserMember.setBindStatus("1");
						wxUserMemberService.updateNotNull(wxUserMember);
					}
					
				}
			}

			// 获取用户信息
			String jwt = JsonWebTokenUtil.issueJWT(openId, memberInfo.getMemberId(), hotelId,
					JwtFilter.CLIENT_MINI_PROGRAM, period, "user", null, HotelConstant.LOGIN_TYPE_MOBILE_ClIENT,
					SignatureAlgorithm.HS512);
			return RestResultGenerator.genSuccessResult(new SessionModel(jwt, HotelConstant.LOGIN_TYPE_MOBILE_ClIENT));
		} catch (Exception e) {
			e.printStackTrace();
			return RestResultGenerator.genResult(false, null, e.getMessage());
		}

	}

	/**
	 * 手机号解除绑定
	 * 
	 * @param mobile
	 * @param vercode
	 * @return
	 */
	@ApiOperation(value = "手机号解除绑定", notes = "手机号解除绑定")
	@RequestMapping(value = "/unbindmobile", method = RequestMethod.GET)
	public RestResult<MemberModel> unbindmobile(ServletRequest request) {

		String memberId = null;

		// 验证vercode是否正确,如果正确返回sessionid，如果不正确返回验证失败信息。
		String subject = (String) request.getAttribute("subject");
		String type = (String) request.getAttribute("type");
		String openId = (String) request.getAttribute("openid");

		// 微信登录，未手机登录
		if (HotelConstant.LOGIN_TYPE_WX.equals(type)) {
			memberId = subject;
		} else {
			return RestResultGenerator.genResult(false, null, "invalid data");
		}

		WXUser wxUser = wxUserService.findUserByOpenid(openId);
		List<WXUserMember> wxUserMemberList = this.wxUserMemberService.findByWXUserId(wxUser.getWxuserId(), memberId);
		for (WXUserMember wm : wxUserMemberList) {
			wm.setUnbindDate(new Date());
			wm.setBindStatus("0");
			this.wxUserMemberService.updateNotNull(wm);
		}

		return RestResultGenerator.genResult(true, null, "解绑成功");
	}

	/**
	 * 判断session是否为登录态
	 * 
	 * @param mobile
	 * @param vercode
	 * @return
	 */
	@ApiOperation(value = "验证sessionid", notes = "验证sessionid")
	@RequestMapping(value = "/isLoginSessionId", method = RequestMethod.GET)
	public RestResult<Boolean> isLoginSessionId(ServletRequest request) {

		String memberId = null;
		// 验证vercode是否正确,如果正确返回sessionid，如果不正确返回验证失败信息。
		String subject = (String) request.getAttribute("subject");
		String type = (String) request.getAttribute("type");
		// 微信登录，未手机登录
		if (HotelConstant.LOGIN_TYPE_WX.equals(type)) {
			memberId = subject;
		} else {
			return RestResultGenerator.genResult(false, null, "invalid data");
		}
		if (memberId != null && !"".equals(memberId)) {
			return RestResultGenerator.genResult(true, null, "验证通过");
		}
		return RestResultGenerator.genResult(false, false, "you are not logged in!");
	}

	/**
	 * 获取登录用户基本信息
	 * 
	 * @param mobile
	 * @param vercode
	 * @return
	 * @throws Exception 
	 */
	@ApiOperation(value = "获取登录用户基本信息", notes = "获取登录用户基本信息")
	@RequestMapping(value = "/getLoginUserInfo", method = RequestMethod.GET)
	public RestResult<MemberModel> getLoginUserInfo(ServletRequest request) throws Exception {

		try {
			String memberId = (String) request.getAttribute("memberId");
			// 验证vercode是否正确,如果正确返回sessionid，如果不正确返回验证失败信息。
			String subject = (String) request.getAttribute("subject");
			String type = (String) request.getAttribute("type");
			String openId = (String) request.getAttribute("openid");
			String hotelId = (String)request.getAttribute("issuer") ;
			// 微信登录，未手机登录
			if (HotelConstant.LOGIN_TYPE_WX.equals(type) || HotelConstant.LOGIN_TYPE_MOBILE_ClIENT.equals(type)) {
				memberId = subject;
			} else {
				return RestResultGenerator.genResult(false, null, "invalid data");
			}

			
			if (memberId != null && !"".equals(memberId)) {
				// 返回用户基本信息
				MemberInfo member = this.memberInfoService.selectByKey(memberId);
				if (member == null) {
					return RestResultGenerator.genErrorResult("invalid member id:" + memberId);
				}
				MemberModel memberModel = new MemberModel();
				BeanUtils.copyProperties(member, memberModel);
				// 获取微信相关信息
				WXUser wxUser = wxUserService.findUserByOpenid(openId);
				//进行解码
				String nickname = wxUser.getNickName();
				nickname = new String(Base64.decode(nickname),"UTF-8");
				wxUser.setNickName(nickname);
				wxUser.setName(nickname);
				BeanUtils.copyProperties(wxUser, memberModel, "mobile");
				
				// 统计用户积分信息，直接把用户在当前酒店中所有已完成的订单金额相加。
				// t_order_info --> t_member_account_log(l.real_money)
				if(!StringUtils.isBlank(hotelId)) {
					BigDecimal incom = orderService.countMemberOrdersIncome(memberId, hotelId) ;
					memberModel.setCredit(incom);
				}else {
					memberModel.setCredit(new BigDecimal("0"));
				}

				// 废弃代码。目前房间折扣信息直接在后台计算，不在前端计算，因此这这两个字段前端不在需要
				// memberModel.setDiscountType("1");// 直减
				// memberModel.setDiscount("10");

				return RestResultGenerator.genSuccessResult(memberModel);
			} else {
				return RestResultGenerator.genErrorResult("invalid session id");
			}

		} catch (BeansException e) {
			e.printStackTrace();
			return RestResultGenerator.genErrorResult(e.getMessage());
		}

	}

	/**
	 * 会员充值
	 * 
	 * @param userId
	 * @param couponId
	 * @param amount
	 *            充值金额
	 * @return
	 */
	@ApiOperation(value = "会员充值", notes = "会员充值")
	@RequestMapping(value = "recharge", method = RequestMethod.POST)
	public RestResult deposit(String wxcfgid, Integer couponId, BigDecimal money, ServletRequest request) {

		try {
			// 设置默认服务器地址
			if (miniprogramServerUrl == null) {
				return RestResultGenerator.genErrorResult("小程序服务器域名异常");
			}
			// 第一步：调用小程序openapi 得到openid
			String openId = (String) request.getAttribute("openid");
			String type = (String) request.getAttribute("type");
			String hotelId = "";
			String memberId = "";
			// 客户端绑定后登录
			if (HotelConstant.LOGIN_TYPE_MOBILE_ClIENT.equals(type)) {
				hotelId = (String) request.getAttribute("issuer");
				memberId = (String) request.getAttribute("subject");
			} else {
				return RestResultGenerator.genErrorResult("请先手机登录");
			}

			HotelInfo hotel = hotelService.findHotelsById(hotelId);
			if (hotel == null) {
				return RestResultGenerator.genErrorResult("不存在的酒店ID");
			}
			// 第二步：生成客户订单
			// 生成充值订单
			DepositOrder depositOrder = depositOrderService.saveDepositOrder(hotelId, memberId, couponId, money);

			String createdIp = request.getRemoteAddr();
			String notifyUrl = miniprogramServerUrl + "/rest/members/" + wxcfgid + "/" + depositOrder.getDepositId()
					+ "/depositResultNotify";
			// 创建支付订单
			PaySignModel model = depositOrderService.createUnifiedOrder(wxcfgid, openId, "充值",
					depositOrder.getDepositId(), couponId, createdIp, notifyUrl, depositOrder.getPayMoney());

			if (model == null) {
				return RestResultGenerator.genErrorResult("can not find specified app configuration");
			} else {
				return RestResultGenerator.genSuccessResult(model);
			}

		} catch (Exception e) {
			e.printStackTrace();
			return RestResultGenerator.genErrorResult("server error");
		}

	}

	/**
	 * 充值结果通知
	 */
	@ApiOperation(value = "充值结果通知", notes = "统计充值金额,由微信服务器通知调用", hidden = true)
	@RequestMapping(value = "/{wxcfgid}/{depositId}/depositResultNotify", method = RequestMethod.POST)
	public void depositResultNotify(@PathVariable("wxcfgid") String wxcfgid,
			@PathVariable("depositId") String depositId, HttpServletRequest request) {
		try (InputStream ins = request.getInputStream();) {
			byte[] bs = new byte[1024];
			int i = 0;
			String str = "";
			while ((i = ins.read(bs)) != -1) {
				str += new String(bs, 0, i);
			}

			JSONObject json = XmlTool.documentToJSONObject(str);
			PayResult res = JSON.toJavaObject(json, PayResult.class);

			if ("SUCCESS".equals(res.getResult_code())) {
				String outTradeNo = res.getOut_trade_no();
				if (outTradeNo != null && outTradeNo.equals(depositId)) {
					DepositOrder order = depositOrderService.selectByKey(depositId);
					// 验证订单id
					if (order == null) {
						throw new RuntimeException("invalid order id(非法的订单id)");
					}
					// 状态已支付直接返回
					if ("1".equals(order.getPayStatus())) {
						return;
					}
					// 验证签名
					SortedMap<String, Object> generals = new TreeMap<>();
					XmlTool.JsonToMap(json, generals);
					generals.remove("sign");

					WxCfg wxcfg = wxCfgService.selectByKey(wxcfgid);
					String sign = SignatureUtil.sign(generals, wxcfg.getAppkey());
					if (!sign.equals(json.get("sign"))) {
						throw new RuntimeException("pay notify sign invalid(支付通知无效)");
					}
					BigDecimal totalFee = new BigDecimal(res.getTotal_fee());
					// 判断金额是否相等(数据库金额为元，需要*100换算成分后进行比较)
					if (totalFee.compareTo(order.getPayMoney().multiply(BigDecimal.valueOf(100))) != 0) {
						throw new RuntimeException("invalid order notify(非法的同步消息)");
					}
					// 记录充值消费
					MemberAccountLog accountLog = new MemberAccountLog();
					accountLog.setHotelId(order.getHotelId() + "");
					accountLog.setMemberId(order.getMemberId());
					accountLog.setType("3");
					accountLog.setPayStatus("1");
					accountLog.setPayMode("2"); // 充值
					accountLog.setPayTime(df.format(new Date()));
					accountLog.setCouponId(order.getCouponId() + "");
					accountLog.setRealMoney(order.getRealMoney());
					accountLog.setVirtMoney(order.getVirtMoney());
					accountLog.setAddTime(df.format(new Date()));
					memberInfoService.insertConsumingRecord(accountLog); // 写入用户消费记录
					// 会员充值
					depositOrderService.depositMemberAccount(depositId);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取充值成功与否状态
	 */
	@ApiOperation(value = "获取充值成功与否状态", notes = "获取充值成功与否状态")
	@RequestMapping(value = "rechargeResult/{depositId}", method = RequestMethod.GET)
	public RestResult depositResult(String depositId) {
		DepositOrder order = depositOrderService.selectByKey(depositId);
		if (order != null) {
			if ("0".equals(order.getPayStatus())) {
				return RestResultGenerator.genSuccessResult("no return");
			}

			if ("1".equals(order.getPayStatus())) {
				return RestResultGenerator.genSuccessResult("ok");
			}
			if ("2".equals(order.getPayStatus())) {
				return RestResultGenerator.genSuccessResult("fail");
			}
		}

		return RestResultGenerator.genErrorResult("err");

	}

	/**
	 * 统计当天新注册用户数
	 * 
	 * @param hotelId
	 *            酒店id
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return
	 */
	@ApiOperation(value = "当天新注册用户数", notes = "统计当天新注册用户数")
	@RequestMapping(value = "todayNewRegUsers", method = RequestMethod.GET)
	public RestResult<Integer> todayNewRegUsers(@RequestParam(required = true) String hotelId) {

		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		String startTime = LocalDate.now().format(formatter);
		String endTime = LocalDate.now().format(formatter);

		Integer count = this.memberInfoService.countNewMember(hotelId, HotelConstant.USER_GRADE_NEW, startTime,
				endTime);
		return RestResultGenerator.genSuccessResult(count);
	}

	/**
	 * 统计当天新注册会员数
	 * 
	 * @param hotelId
	 *            酒店id
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return
	 */
	@ApiOperation(value = "当天新注册会员数", notes = "统计当天新注册会员数")
	@RequestMapping(value = "todayNewRegMembers", method = RequestMethod.GET)
	public RestResult<Integer> todayNewRegMembers(@RequestParam(required = true) String hotelId) {

		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		String startTime = LocalDate.now().format(formatter);
		String endTime = LocalDate.now().format(formatter);

		Integer count = this.memberInfoService.countNewMember(hotelId, HotelConstant.USER_GRADE_MEMBER, startTime,
				endTime);
		return RestResultGenerator.genSuccessResult(count);
	}

	/**
	 * 统计新注册用户数
	 * 
	 * @param hotelId
	 *            酒店id
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return
	 */
	@ApiOperation(value = "新注册用户数", notes = "统计新注册用户数")
	@RequestMapping(value = "newRegUsers", method = RequestMethod.GET)
	public RestResult<Integer> countNewRegUsers(@RequestParam(required = true) String hotelId, String startTime,
			String endTime) {
		Integer count = this.memberInfoService.countNewMember(hotelId, HotelConstant.USER_GRADE_NEW, startTime,
				endTime);
		return RestResultGenerator.genSuccessResult(count);
	}

	/**
	 * 统计新注册会员数
	 * 
	 * @param hotelId
	 *            酒店id
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return
	 */
	@ApiOperation(value = "统计新注册会员数", notes = "新注册会员数")
	@RequestMapping(value = "newRegMembers", method = RequestMethod.GET)
	public RestResult<Integer> countNewRegMembers(@RequestParam(required = true) String hotelId, String startTime,
			String endTime) {
		Integer count = this.memberInfoService.countNewMember(hotelId, HotelConstant.USER_GRADE_MEMBER, startTime,
				endTime);
		return RestResultGenerator.genSuccessResult(count);
	}

	/**
	 * 统计充值金额
	 * 
	 * @param hotelId
	 *            酒店id
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return
	 */
	@ApiOperation(value = "统计充值金额", notes = "统计充值金额")
	@RequestMapping(value = "countRechargeAmount", method = RequestMethod.GET)
	public RestResult<Integer> countRechargeAmount(@RequestParam(required = true) String hotelId, String startTime,
			String endTime) {

		return RestResultGenerator.genSuccessResult(1000000);
	}

	public MemberModel getUserInfo() {
		MemberModel member = new MemberModel();
		member.setMemberId(UUID.randomUUID().toString());
		member.setHotelId(UUID.randomUUID().toString());
		member.setGrade(HotelConstant.USER_GRADE_NEW);
		member.setRealMoney(BigDecimal.valueOf(500));
		member.setVirtMoney(BigDecimal.valueOf(200));
		member.setMobile("18700000000");
		return member;
	}

	/**
	 * 保存会员信息
	 * 
	 * @param member
	 * @return
	 */
	@ApiOperation(value = "保存会员信息", notes = "用户授权成功后，保存会员信息")
	@RequestMapping(value = "saveMemberInfo", method = RequestMethod.POST)
	public RestResult saveMemberInfo(WXUserModel wxuserModel, ServletRequest request) {
		try {

			String type = (String) request.getAttribute("type");
			String subject = (String) request.getAttribute("subject");
			String wxUserId = null;
			// 微信登录，未手机登录
			if (HotelConstant.LOGIN_TYPE_WX.equals(type) || HotelConstant.LOGIN_TYPE_MOBILE_ClIENT.equals(type)) {
				wxUserId = subject;
			} else {
				return RestResultGenerator.genResult(false, null, "invalid session id");
			}

			WXUser wxUser = this.wxUserService.selectByKey(wxUserId);
			if (wxUser == null) {
				return RestResultGenerator.genResult(false, null, "saveMemberInfo方法中wxUser is null");
			}
			BeanUtils.copyProperties(wxuserModel, wxUser);
			String nickname = wxUser.getNickName();
			 //进行编码
			 nickname =Base64.encodeToString(nickname.getBytes("UTF-8"));
			 wxUser.setNickName(nickname);
			 wxUser.setName(nickname);
			String openId = (String) request.getAttribute("openid");
			if(StringUtils.isBlank(openId)) {
				return RestResultGenerator.genErrorResult("saveMemberInfo方法中openid is null"+"wxUserId======"+wxUserId);
			}
			wxUser.setOpenid(openId);
			wxUser.setRegTime(new Date());
			wxUserService.updateNotNull(wxUser);
			return RestResultGenerator.genSuccessResult();
		} catch (Exception e) {
			e.printStackTrace();
			return RestResultGenerator.genErrorResult(e.getMessage());
		}
	}

	/**
	 * 获取用户消费记录
	 * 
	 * @param member
	 * @return
	 */
	@ApiOperation(value = "获取用户消费记录", notes = "获取用户消费记录")
	@RequestMapping(value = "getConsumingRecord", method = RequestMethod.GET)
	public RestResult<List<MemberAccountLog>> getConsumingRecord(ServletRequest request) {
		try {
			String type = (String) request.getAttribute("type");

			if (!HotelConstant.LOGIN_TYPE_MOBILE_ClIENT.equals(type)) {// c端
				return RestResultGenerator.genErrorResult("loginType is invalid ");
			}
			String hotelId = (String) request.getAttribute("issuer");
			String memberId = (String) request.getAttribute("subject");
			// 获取用户id,酒店id
			List<MemberAccountLog> list = memberInfoService.getConsumingRecordByUser(hotelId, memberId, null, "1");
			return RestResultGenerator.genSuccessResult(list);
		} catch (Exception e) {
			e.printStackTrace();
			return RestResultGenerator.genErrorResult(e.getMessage());
		}
	}

}
